/*
* $Id$
* Copyright (c) 2008-2010 Insprise Software (Shanghai) Co. Ltd.
* All Rights Reserved
* Changelog:
*   Li Guoliang - Jan 16, 2010: Initial version
*/

package com.bizfx.component.controls
{
import flash.events.Event;
import flash.events.MouseEvent;

import com.bizfx.utils.ListUtils;

import mx.collections.ArrayCollection;
import mx.collections.ICollectionView;
import mx.containers.HBox;
import mx.controls.CheckBox;
import mx.controls.treeClasses.ITreeDataDescriptor;
import mx.controls.treeClasses.TreeItemRenderer;
import mx.controls.treeClasses.TreeListData;
import mx.logging.ILogger;
import mx.logging.Log;

/**
 * TreeCheckable 的 ItemRender
 * 增加了CheckBox, 并进行一部分CheckBox状态改变后的相关操作.
 */
public class CheckBoxTreeItemRenderer extends TreeItemRenderer
{
	private static const log:ILogger = Log.getLogger("TreeCheckableItemRender");

	/** UI */
	protected var _checkBox:CheckBox;

	/** Modeling */
	protected var _item:Object;
	protected var _checkedItems:ArrayCollection;

	// Constructor
	public function CheckBoxTreeItemRenderer() {
		super();
	}

	private function ownerEnableChangedHandler(event:Event):void {
		if(this._checkBox) {
			_checkBox.enabled = (owner as CheckBoxTree).enabled;
			this.label.enabled = true;
			this.enabled = true;
		}
	}
	/** @inheritDoc */
	override public function set data(value:Object) : void {
		super.data = value;

		if(value == null) {
			return;
		}
		_item = value;
	}

	/** @inheritDoc */
	override protected function createChildren() : void {
		super.createChildren();
		label.addEventListener(MouseEvent.CLICK, onLabelClicked);
		_checkBox = new CheckBox(); // 初始化UI.
		_checkBox.addEventListener(Event.CHANGE, onCheckBoxChanged);
		_checkBox.enabled = (owner as CheckBoxTree).enabled;
		this.owner.addEventListener("checkBoxTreeEnabledChanged", ownerEnableChangedHandler);
		addChild(_checkBox);
	}
	
	/** @inheritDoc */
	override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number) : void {
		super.updateDisplayList( unscaledWidth, unscaledHeight );
		
		var startx: Number = data ? ( listData as TreeListData ).indent : 0;
		
		if ( disclosureIcon )
		{
			disclosureIcon.x = startx;
			startx = disclosureIcon.x + disclosureIcon.width;
			disclosureIcon.setActualSize( disclosureIcon.width, disclosureIcon.height );
			disclosureIcon.visible = data ? ( listData as TreeListData ).hasChildren : false;
		}
		
		if ( icon )
		{
			icon.x = startx;
			startx = icon.x + icon.measuredWidth;
			icon.setActualSize(icon.measuredWidth, icon.measuredHeight);
		}
		
		if( _checkBox )
		{
			_checkBox.x = startx;
			startx = _checkBox.x + _checkBox.measuredWidth;
			_checkBox.setActualSize( _checkBox.measuredWidth, _checkBox.measuredHeight );
		}
		
		label.x = startx;
		label.setActualSize( unscaledWidth - startx, measuredHeight );
		
		var verticalAlign:String = getStyle("verticalAlign");
		
		if (verticalAlign == "top")
		{
			label.y = 0;
			_checkBox.y = 0;
			
			if ( icon )
				icon.y = 0;
			if ( disclosureIcon )
				disclosureIcon.y = 0;
		} else if ( verticalAlign == "bottom")
		{
			label.y = unscaledHeight - label.height + 2; // 2 for gutter
			_checkBox.y = unscaledHeight - _checkBox.height + 2; // 2 for gutter
			if ( icon )
				icon.y = unscaledHeight - icon.height;
			if ( disclosureIcon )
				disclosureIcon.y = unscaledHeight - disclosureIcon.height;
		} else
		{
			label.y    = ( unscaledHeight - label.height ) / 2;
			_checkBox.y = ( unscaledHeight - _checkBox.height ) / 2;
			if ( icon )
				icon.y = ( unscaledHeight - icon.height ) / 2;
			if ( disclosureIcon )
				disclosureIcon.y = ( unscaledHeight - disclosureIcon.height ) / 2;
		}
		_checkedItems = (owner as CheckBoxTree).checkedItems;
		_checkBox.selected = ListUtils.isContains(_item, _checkedItems);// isIn(_item, _checkedItems);
	}

	override protected function measure():void
	{
		super.measure();
		
		var w:Number = data ? ( listData as TreeListData ).indent : 0;
		
		if ( disclosureIcon )
			w += disclosureIcon.width;
		
		if ( icon )
			w += icon.measuredWidth;
		
		if ( label.width < 4 || label.height < 4 )
		{
			label.width  = 4;
			label.height = 16;
		}
		
		if ( isNaN( explicitWidth ) )
		{
			w += label.getExplicitOrMeasuredWidth( );
			w += _checkBox.getExplicitOrMeasuredWidth( );	
			measuredWidth  = w;
			measuredHeight = Math.max( _checkBox.getExplicitOrMeasuredHeight( ), label.getExplicitOrMeasuredHeight( ) );
		}
		else
		{
			label.width = Math.max(explicitWidth - ( w + _checkBox.getExplicitOrMeasuredWidth( ) ), 4 );
			measuredHeight = Math.max( _checkBox.getExplicitOrMeasuredHeight( ), label.getExplicitOrMeasuredHeight( ) );
			
			if ( icon && icon.measuredHeight > measuredHeight )
				measuredHeight = icon.measuredHeight;
		}
	}
	
	/** 当Label被点击时响应 - 改变CheckBox状态. */
	protected function onLabelClicked(e:MouseEvent):void {
		trace("当前点击的对象: " + _item.toString());
		//		_checkBox.selected = !_checkBox.selected;
		//		_checkedItems = (owner as TreeCheckable).checkedItems;
		//		if(_checkBox.selected) {
		//			_checkedItems.addItem(_item);
		//		}else {
		//			_checkedItems.removeItemAt(_checkedItems.getItemIndex(_item));
		//		}
	}

	/**
	 * 当CheckBox被点击时响应.
	 * 1. 改变当前选定项目状态
	 * 2. 改变上级及下级项目状态
	 * 3. 如果为选定, 则展开下级项目.
	 **/
	protected function onCheckBoxChanged(e:Event):void {
		var tree:CheckBoxTree = owner as CheckBoxTree;
		if(_checkBox.selected) {
			tree.addCheckedItem(_item);
			tree.expandChildrenOf(_item, true);
		}else {
			tree.removeCheckedItem(_item);
			// _checkedItems.removeItemAt(_checkedItems.getItemIndex(_item));
		}
		checkParent(_item);
		checkChild(_item);
		tree.invalidateList();
	}

	/** 递归的选中父项目. */
	protected function checkParent(treeItem:Object):void {
		var tree:CheckBoxTree = owner as CheckBoxTree;
		var parentItem:Object = tree.getParentItem(treeItem);
		if(parentItem == null) {
			return;
		}

		var treeDD:ITreeDataDescriptor = tree.dataDescriptor;

		if(ListUtils.isContains(treeItem, _checkedItems)) { // 如果当前处理项目已选定.
			tree.addCheckedItem(parentItem);
			// log.info("选定上级项目: " + parentItem);
		}else if(isAllItemUnChecked(treeDD.getChildren(parentItem))) { // 如果所有同级别项目都未选定, 则反选上级项目
			tree.removeCheckedItem(parentItem);
			// log.info("同级别项目都未选定, 反选上级项目: " + parentItem);
		}
		checkParent(parentItem);
	}

	/**
	 * 递归的选中/反选子项目.
	 */
	protected function checkChild(treeItem:Object):void {
		var tree:CheckBoxTree = owner as CheckBoxTree;
		var treeDD:ITreeDataDescriptor = (owner as CheckBoxTree).dataDescriptor;
		if(treeDD.hasChildren(treeItem)) {
			var children:ICollectionView = treeDD.getChildren(treeItem);
			for each(var obj:Object in children) {
				if(_checkBox.selected) {
					tree.addCheckedItem(obj);
				}else if(!_checkBox.selected){
					tree.removeCheckedItem(obj);
				}
				checkChild(obj);
			}
		}
	}

	/** 检查是否所有的项目都未选定. */
	protected function isAllItemUnChecked(items:ICollectionView):Boolean {
		for each(var obj:Object in items) {
			if(ListUtils.isContains(obj, _checkedItems)) {
				return false;
			}
		}
		return true;
	}
} // end class
} // end package